/*
 * Tile.h
 *
 *  Created on: 2009/01/29
 *      Author: Yongshik Cho
 */

#ifndef TILE_H_
#define TILE_H_

#include <map>
#include "RenderObject.h"
#include "active/Animatable.h"
#include "active/Tweenable.h"
#include "sqplus/sqplus.h"

using namespace SqPlus;

class Tile: public RenderObject
{
public:
	Tile(Texture* texture = 0, uint32 xCount = 1, uint32 yCount = 1);
	virtual ~Tile();

public:
	virtual void devide(uint32 xCount = 1, uint32 yCount = 1);
	virtual void render();

	virtual void animate(const String& anim);
	virtual void animate(const uint32 index);
	virtual void animate(const String& anim, const uint8 loopType, const uint32 loopCount);
	virtual void animate(const uint32 index, const uint8 loopType, const uint32 loopCount);
	virtual void tween(const String& tween);
	virtual void tween(const uint32 index);
	virtual void tween(const String& tween, const uint8 loopType, const uint32 loopCount);
	virtual void tween(const uint32 index, const uint8 loopType, const uint32 loopCount);

	inline void setAnimatable(const String& anim, Animatable* ani)
	{
		Tile* same = mSameAnimationTile;
		if(!same)
			same = this;

		if(!ani)
			return;

		same->mAnimatables[anim] = ani;
	}
	virtual void setTweenable(const String& tween, Tweenable* twn);

	Animatable* getAnimatable()
	{
		Tile* same = mSameAnimationTile;
		if(!same)
			same = this;

		return same->mAnimatable;
	}
	Tweenable* getTweenable()
	{
		Tile* same = mSameTweenTile;
		if(!same)
			same = this;

		return same->mTweenable;
	}

	Animatable* getAnimatable(const String& anim)
	{
		Tile* same = mSameAnimationTile;
		if(!same)
			same = this;

		for(AnimationType::iterator it=same->mAnimatables.begin();it!=same->mAnimatables.end();++it)
		{
			if((*it).first == anim)
				return (*it).second;
		}

		return 0;
	}
	Tweenable* getTweenable(const String& tween)
	{
		Tile* same = mSameTweenTile;
		if(!same)
			same = this;

		for(TweenType::iterator it=same->mTweenables.begin();it!=same->mTweenables.end();++it)
		{
			if((*it).first == tween)
				return (*it).second;
		}

		return 0;
	}

	Animatable* getAnimatable(const uint32 index)
	{
		Tile* same = mSameAnimationTile;
		if(!same)
			same = this;

		if(!same->mAnimatables.size())
			return 0;

		uint32 i = 0;
		for(AnimationType::iterator it=same->mAnimatables.begin();it!=same->mAnimatables.end();++it, ++i)
		{
			if(i == index)
			{
				return (*it).second;
			}
		}

		return 0;
	}
	Tweenable* getTweenable(const uint32 index)
	{
		Tile* same = mSameTweenTile;
		if(!same)
			same = this;

		if(!same->mTweenables.size())
			return 0;

		uint32 i = 0;
		for(TweenType::iterator it=same->mTweenables.begin();it!=same->mTweenables.end();++it, ++i)
		{
			if(i == index)
			{
				return (*it).second;
			}
		}

		return 0;
	}

	const String getAnimationName(const uint32 index)
	{
		Tile* same = mSameAnimationTile;
		if(!same)
			same = this;

		if(!same->mAnimatables.size())
			return String(_T(""));

		uint32 i = 0;
		for(AnimationType::iterator it=same->mAnimatables.begin();it!=same->mAnimatables.end();++it, ++i)
		{
			if(i == index)
			{
				return (*it).first;
			}
		}
	}
	const String getTweenName(const uint32 index)
	{
		Tile* same = mSameTweenTile;
		if(!same)
			same = this;

		if(!same->mTweenables.size())
			return String(_T(""));

		uint32 i = 0;
		for(TweenType::iterator it=same->mTweenables.begin();it!=same->mTweenables.end();++it, ++i)
		{
			if(i == index)
			{
				return (*it).first;
			}
		}
	}

	inline const uint32 getAnimationCount()
	{
		Tile* same = mSameAnimationTile;
		if(!same)
			same = this;

		return (uint32)same->mAnimatables.size();
	}

	inline const uint32 getTweenCount()
	{
		Tile* same = mSameTweenTile;
		if(!same)
			same = this;

		return (uint32)same->mTweenables.size();
	}

	inline Tile* getSameAnimationTile() { return mSameAnimationTile; }
	inline void setSameAnimationTile(RenderObject* ro) { mSameAnimationTile = (Tile*)ro; }

	inline Tile* getSameTweenTile() { return mSameTweenTile; }
	inline void setSameTweenTile(RenderObject* ro) { mSameTweenTile = (Tile*)ro; }

protected:
	typedef map<String, Animatable*> AnimationType;
	typedef map<String, Tweenable*> TweenType;
	AnimationType		mAnimatables;
	TweenType			mTweenables;
	Animatable*			mAnimatable;
	Tweenable*			mTweenable;
	Tile*				mSameAnimationTile;
	Tile*				mSameTweenTile;
};

//must be declared here
DECLARE_INSTANCE_TYPE(Tile)

#endif /* TILE_H_ */
